home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
haeberli
/
libgutil
/
render.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
16KB
|
822 lines
/*
* Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
* render -
* Help use the graphics library to generate high resolution
* rendered images.
*
* Paul Haeberli - 1988
*/
#include "gl.h"
#include "glmode.h"
#include "values.h"
#include "math.h"
#include "image.h"
#include "vect.h"
#include "izoom.h"
static setvp();
static zoomadd();
static makename();
static makeframe();
static int orthomode = 0;
static float rl = -0.2;
static float rr = 0.2;
static float rb = -0.2;
static float rt = 0.2;
static float rnear = 1.0;
static float rfar = 100.0;
static float raspect = 1.0;
static float rfocus = 5.0;
static float raperture = 1.0;
static float rpixeldiameter = 1.0;
static float ox1, ox2, oy1, oy2, oz1, oz2;
static int vpxsize, vpysize;
/*
* general rendering stuff follows
*
*
*/
renderperspective(fov,aspect,near,far)
int fov;
float aspect, near, far;
{
renderfperspective(fov/10.0,aspect,near,far);
}
renderfperspective(fov,aspect,near,far)
float fov;
float aspect, near, far;
{
float tanval;
tanval = near*tan(fov*M_PI/360.0);
renderwindow(-tanval*aspect,tanval*aspect,-tanval,tanval,near,far);
}
renderwindow(l,r,b,t,near,far)
float l,r,b,t,near,far;
{
rl = l;
rr = r;
rb = b;
rt = t;
rnear = near;
rfar = far;
raspect = (r-l)/(t-b);
orthomode = 0;
restorewindow();
}
getrenderwindow(l,r,b,t,near,far)
float *l,*r,*b,*t,*near,*far;
{
*l = rl;
*r = rr;
*b = rb;
*t = rt;
*near = rnear;
*far = rfar;
}
renderortho(x1,x2,y1,y2,z1,z2)
float x1,x2,y1,y2,z1,z2;
{
ortho(x1,x2,y1,y2,z1,z2);
ox1 = x1;
ox2 = x2;
oy1 = y1;
oy2 = y2;
oz1 = z1;
oz2 = z2;
orthomode = 1;
}
set35mmlens(focallength)
float focallength;
{
float dx, dy;
dx = 18.0*(rnear/focallength);
dy = 12.0*(rnear/focallength);
renderwindow(-dx,dx,-dy,dy,rnear,rfar);
}
setzclip(near,far)
float near, far;
{
rnear = near;
rfar = far;
restorewindow();
}
setfocus(focus)
float focus;
{
rfocus = focus;
}
setaperture(aper)
float aper;
{
raperture = aper;
}
setpixeldiameter(d)
float d;
{
rpixeldiameter = d;
}
setlensangle(angle)
float angle;
{
renderfperspective(angle,raspect,rnear,rfar);
}
static float wpixdx, wpixdy;
static float weyedx, weyedy;
static float wfocus;
accset(pixdx,pixdy,eyedx,eyedy)
float pixdx,pixdy,eyedx,eyedy;
{
wpixdx = pixdx*rpixeldiameter;
wpixdy = pixdy*rpixeldiameter;
weyedx = eyedx*raperture;
weyedy = eyedy*raperture;
restorewindow();
}
restorewindow()
{
accwindow(rl,rr,rb,rt,rnear,rfar,wpixdx,wpixdy,weyedx,weyedy,rfocus);
}
/*
* accwindow -
* Just like the window command, but lets you do
* sub-pixel positioning, depth of field, and stereo,
*
* Paul Haeberli - 1989
*
*/
accwindow(l,r,b,t,near,far,pixdx,pixdy,eyedx,eyedy,focus)
float l, r, b, t, near, far;
float pixdx, pixdy, eyedx, eyedy, focus;
{
short vx1, vx2, vy1, vy2;
float xwsize, ywsize;
float dx, dy;
int xpixels, ypixels;
if(focus<0.0)
focus = -focus;
getviewport(&vx1,&vx2,&vy1,&vy2);
xpixels = vx2-vx1+1;
ypixels = vy2-vy1+1;
xwsize = r-l;
ywsize = t-b;
dx = -(pixdx*xwsize/xpixels+eyedx*near/focus);
dy = -(pixdy*ywsize/ypixels+eyedy*near/focus);
mmode(MPROJECTION);
window(l+dx,r+dx,b+dy,t+dy,near,far);
translate(-eyedx,-eyedy,0.0);
mmode(MVIEWING);
}
accortho()
{
fprintf(stderr,"accortho: not implemented\n");
}
vpsize(xsize,ysize)
int xsize, ysize;
{
vpxsize = xsize;
vpysize = ysize;
}
getvpsize(xsize,ysize)
int *xsize, *ysize;
{
short vx1, vx2, vy1, vy2;
getviewport(&vx1,&vx2,&vy1,&vy2);
*xsize = vx2-vx1+1;
*ysize = vy2-vy1+1;
}
clipvol(x,y,z,p)
int x, y, z;
vect *p;
{
float zp;
long near, far;
getzviewport(&near,&far);
p->x = 2.0*(x+0.5)/vpxsize - 1.0;
p->y = 2.0*(y+0.5)/vpysize - 1.0;
p->z = 2.0*((float)(z-near))/(far-near) - 1.0;
}
/*
* Various render drawing functions
*
*
*/
rendertoscreen(drawfunc)
int (*drawfunc)();
{
mmode(MPROJECTION);
if(orthomode)
ortho(ox1,ox2,oy1,oy2,oz1,oz2);
else
window(rl,rr,rb,rt,rnear,rfar);
mmode(MVIEWING);
pushmatrix();
(drawfunc)();
popmatrix();
}
renderstereo(drawfunc)
int (*drawfunc)();
{
}
rendersubpix(drawfunc,xoffset,yoffset)
int (*drawfunc)();
float xoffset, yoffset;
{
mmode(MPROJECTION);
if(orthomode)
accortho(ox1,ox2,oy1,oy2,oz1,oz2,xoffset,yoffset,0.0,0.0,1.0);
else
accset(xoffset,yoffset,0.0,0.0);
mmode(MVIEWING);
pushmatrix();
(drawfunc)();
popmatrix();
}
shiftrender(drawfunc,xshift,yshift)
int (*drawfunc)();
float xshift, yshift;
{
if(orthomode) {
fprintf(stderr,"shift render: huh?\n");
exit(1);
} else {
accset(0.0,0.0,xshift,yshift);
}
pushmatrix();
(drawfunc)();
popmatrix();
}
subshiftrender(drawfunc,xsub,ysub,xshift,yshift)
int (*drawfunc)();
float xsub, ysub, xshift, yshift;
{
mmode(MPROJECTION);
if(orthomode) {
fprintf(stderr,"shift render: huh?\n");
exit(1);
} else {
accset(xsub,ysub,xshift,yshift);
}
mmode(MVIEWING);
pushmatrix();
(drawfunc)();
popmatrix();
}
rendertofile(drawfunc,outname,xsize,ysize)
int (*drawfunc)();
char *outname;
int xsize, ysize;
{
char filename[40];
char assemblecmd[4069];
char removecmd[4069];
char syscmd[4069];
long xdraw, ydraw;
int x, y, nx, ny;
int fno;
getsize(&xdraw,&ydraw);
reshapeviewport();
if(xsize<=xdraw && ysize<=ydraw) {
makeframe(0,0,xdraw,ydraw,xsize,ysize);
pushmatrix();
(drawfunc)();
popmatrix();
savergbwindow("temp000.rgb");
sprintf(syscmd,"subimg temp000.rgb %s 0 %d 0 %d",outname,xsize-1,ysize-1);
system(syscmd);
system("rm temp000.rgb");
} else {
nx = 1+((xsize-1)/xdraw);
ny = 1+((ysize-1)/ydraw);
fno = 0;
sprintf(assemblecmd,"assemble %d %d temp1.rgb ",nx,ny);
sprintf(removecmd,"rm ");
for(y=0; y<ny; y++) {
for(x=0; x<nx; x++) {
makeframe(x,y,xdraw,ydraw,xsize,ysize);
pushmatrix();
(drawfunc)();
popmatrix();
makename(fno++,filename);
strcat(assemblecmd,filename);
strcat(assemblecmd," ");
strcat(removecmd,filename);
strcat(removecmd," ");
savergbwindow(filename);
}
}
system(assemblecmd);
system(removecmd);
sprintf(syscmd,"subimg temp1.rgb %s 0 %d 0 %d",outname,xsize-1,ysize-1);
system(syscmd);
sprintf(syscmd,"rm temp1.rgb");
system(syscmd);
}
if(orthomode)
ortho(ox1,ox2,oy1,oy2,oz1,oz2);
else
window(rl,rr,rb,rt,rnear,rfar);
}
static makename(n,name)
int n;
char *name;
{
sprintf(name,"temp%03d.rgb",n);
}
static makeframe(x,y,xdraw,ydraw,xsize,ysize)
int x, y;
int xdraw, ydraw;
int xsize, ysize;
{
float l, r, b, t;
float x1, x2, y1, y2;
float vsize, hsize;
float xrend, yrend;
mmode(MPROJECTION);
if(orthomode) {
hsize = ox2-ox1;
vsize = oy2-oy1;
xrend = xdraw*(hsize/xsize);
yrend = ydraw*(vsize/ysize);
x1 = ox1+x*xrend;
x2 = x1+xrend;
y1 = oy1+y*yrend;
y2 = y1+yrend;
ortho(x1,x2,y1,y2,oz1,oz2);
} else {
vsize = (rt-rb);
hsize = xsize*(vsize/ysize);
xrend = xdraw*(hsize/xsize);
yrend = ydraw*(vsize/ysize);
l = x*xrend-hsize/2.0;
r = l+xrend;
b = y*yrend-vsize/2.0;
t = b+yrend;
window(l,r,b,t,rnear,rfar);
}
mmode(MVIEWING);
}
/*
* general environment drawing stuff follows
*
*
*/
rendercubetoscreen(drawfunc)
int (*drawfunc)();
{
short x1, x2, y1, y2;
int deltax, deltay;
int xclick, yclick;
int i;
rgb(0.0,0.0,0.0);
clear();
pushviewport();
getviewport(&x1,&x2,&y1,&y2);
deltax = x2-x1;
deltay = y2-y1;
xclick = deltax/4;
yclick = deltay/3;
mmode(MPROJECTION);
perspective(900,1.0/1.0,rnear,rfar);
mmode(MVIEWING);
if(glgetmode() & DOUBLEBUFFER)
glsetmode(INHIBITSWAP,1);
for(i=0; i<6; i++) {
pushmatrix();
switch(i) {
case 0:
setvp(1,1,x1,y1,xclick,yclick);
rot(0.0,'y');
break;
case 1:
setvp(2,1,x1,y1,xclick,yclick);
rot(90.0,'y');
break;
case 2:
setvp(3,1,x1,y1,xclick,yclick);
rot(180.0,'y');
break;
case 3:
setvp(0,1,x1,y1,xclick,yclick);
rot(270.0,'y');
break;
case 4:
setvp(1,2,x1,y1,xclick,yclick);
rot(-90.0,'x');
break;
case 5:
setvp(1,0,x1,y1,xclick,yclick);
rot(90.0,'x');
break;
}
(drawfunc)();
popmatrix();
}
if(glgetmode() & DOUBLEBUFFER) {
glsetmode(INHIBITSWAP,0);
swapbuffers();
}
popviewport();
}
static setvp(xpos,ypos,xorg,yorg,xclick,yclick)
int xpos,ypos,xorg,yorg,xclick,yclick;
{
int x1, x2, y1, y2;
x1 = xorg+(xpos+0)*xclick;
y1 = yorg+(ypos+0)*yclick;
x2 = xorg+(xpos+1)*xclick;
y2 = yorg+(ypos+1)*yclick;
viewport(x1,x2-1,y1,y2-1);
}
rendercylinder(drawfunc,nsides)
int (*drawfunc)();
int nsides;
{
short x1, x2, y1, y2;
float fx1, fx2, xclick;
int deltax, deltay;
int i;
float angleper, angle, tangle;
rgb(0.0,0.0,0.0);
clear();
pushviewport();
getviewport(&x1,&x2,&y1,&y2);
deltax = x2-x1+1;
deltay = y2-y1+1;
xclick = deltax/(float)nsides;
angleper = (2.0*M_PI)/nsides;
tangle = tan(angleper/2);
angle = 2*(180.0*atan(tangle*deltay/xclick))/M_PI;
if(glgetmode() & DOUBLEBUFFER)
glsetmode(INHIBITSWAP,1);
for(i=0; i<nsides; i++) {
fx1 = x1+i*xclick+0.5;
fx2 = x1+(i+1)*xclick+0.5;
viewport((int)fx1,((int)fx2)-1,y1,y2);
mmode(MPROJECTION);
renderfperspective(angle,(float)xclick/deltay,rnear,rfar);
rot(((i+0.5)*360.0)/nsides-90.0-45.0,'y');
mmode(MVIEWING);
pushmatrix();
(drawfunc)();
popmatrix();
}
if(glgetmode() & DOUBLEBUFFER) {
glsetmode(INHIBITSWAP,0);
swapbuffers();
}
popviewport();
}
renderfacestoscreen(drawfunc)
int (*drawfunc)();
{
int i;
char *fixcmd;
mmode(MPROJECTION);
perspective(900,1.0/1.0,rnear,rfar);
mmode(MVIEWING);
for(i=0; i<6; i++) {
pushmatrix();
switch(i) {
case 0:
rot(0.0,'y');
break;
case 1:
rot(90.0,'y');
break;
case 2:
rot(180.0,'y');
break;
case 3:
rot(270.0,'y');
break;
case 4:
rot(-90.0,'x');
break;
case 5:
rot(90.0,'x');
break;
}
(drawfunc)();
popmatrix();
}
}
renderenvtofile(drawfunc,filename)
int (*drawfunc)();
char *filename;
{
int i;
char *savename;
char *fixcmd;
char cmdbuf[256];
mmode(MPROJECTION);
perspective(900,1.0/1.0,rnear,rfar);
mmode(MVIEWING);
for(i=0; i<6; i++) {
pushmatrix();
switch(i) {
case 0:
rot(0.0,'y');
fixcmd = "mv Et.rgb Epx.rgb";
break;
case 1:
rot(90.0,'y');
fixcmd = "iflip Et.rgb Epy.rgb 270";
break;
case 2:
rot(180.0,'y');
fixcmd = "iflip Et.rgb Emx.rgb y";
break;
case 3:
rot(270.0,'y');
fixcmd = "iflip Et.rgb Emy.rgb xy";
break;
case 4:
rot(-90.0,'x');
fixcmd = "iflip Et.rgb Epz.rgb 90";
break;
case 5:
rot(90.0,'x');
fixcmd = "iflip Et.rgb Emz.rgb xy";
break;
}
printf("before it\n");
(drawfunc)();
popmatrix();
savergbwindow("Et.rgb");
system(fixcmd);
printf("after it\n");
}
sprintf(cmdbuf,"assemble 3 2 %s Emx.rgb Emy.rgb Emz.rgb Epx.rgb Epy.rgb Epz.rgb",filename);
system(cmdbuf);
system("rm Et.rgb Emx.rgb Emy.rgb Emz.rgb Epx.rgb Epy.rgb Epz.rgb");
}
/*
* screen saving utilities
*
*/
savergbwindow(name)
char *name;
{
long xsize, ysize;
if(glgetmode()&DOUBLEBUFFER)
readsource(SRC_FRONT);
getsize(&xsize,&ysize);
savergbrect(name,0,0,xsize-1,ysize-1);
if(glgetmode()&DOUBLEBUFFER)
readsource(SRC_BACK);
}
savergbrect(name,x1,y1,x2,y2)
char *name;
int x1, y1, x2, y2;
{
int xsize, ysize;
int y;
IMAGE *oimage;
unsigned long *lbuf, *lptr;
short *rbuf, *gbuf, *bbuf;
int togo, maxrows, thistime;
xsize = x2-x1+1;
ysize = y2-y1+1;
maxrows = 25000/xsize;
lbuf = (unsigned long *)mymalloc(maxrows*xsize*sizeof(unsigned long));
rbuf = (short *)mymalloc(xsize*sizeof(short));
gbuf = (short *)mymalloc(xsize*sizeof(short));
bbuf = (short *)mymalloc(xsize*sizeof(short));
oimage = iopen(name,"w",RLE(1),3,xsize,ysize,3);
if(!oimage) {
fprintf(stderr,"savergbrect: can't open output file\n");
exit(1);
}
togo = ysize;
y = 0;
while(togo) {
thistime = togo;;
if(thistime>maxrows)
thistime = maxrows;
lrectread(x1+0,y1+y,x1+xsize-1,y1+y+thistime-1,lbuf);
togo -= thistime;
lptr = lbuf;
while(thistime--) {
cpacktorgb(lptr,rbuf,gbuf,bbuf,xsize);
putrow(oimage,rbuf,y,0);
putrow(oimage,gbuf,y,1);
putrow(oimage,bbuf,y,2);
lptr += xsize;
y++;
}
}
iclose(oimage);
free(lbuf);
free(rbuf);
free(gbuf);
free(bbuf);
}
zoomrgbwindow(name,factor)
char *name;
int factor;
{
long xsize, ysize;
int ixsize, iysize;
int y;
IMAGE *oimage;
unsigned long *lbuf, *lptr;
short *rbuf, *gbuf, *bbuf;
int togo, maxrows, thistime;
if(glgetmode()&DOUBLEBUFFER)
readsource(SRC_FRONT);
if(factor>11) {
fprintf(stderr,"zoomrgbwindow: factor may not exceed 11\n");
exit(1);
}
getsize(&xsize,&ysize);
ixsize = xsize/factor;
iysize = ysize/factor;
xsize = ixsize*factor;
ysize = iysize*factor;
maxrows = 25000/xsize;
lbuf = (unsigned long *)mymalloc(maxrows*xsize*sizeof(unsigned long));
rbuf = (short *)mymalloc(ixsize*sizeof(short));
gbuf = (short *)mymalloc(ixsize*sizeof(short));
bbuf = (short *)mymalloc(ixsize*sizeof(short));
oimage = iopen(name,"w",RLE(1),3,ixsize,iysize,3);
if(!oimage) {
fprintf(stderr,"zoomrgbwindow: can't open output file\n");
exit(1);
}
togo = ysize;
zerorow(rbuf,ixsize);
zerorow(gbuf,ixsize);
zerorow(bbuf,ixsize);
y = 0;
while(togo) {
thistime = togo;;
if(thistime>maxrows)
thistime = maxrows;
lrectread(0,y,xsize-1,y+thistime-1,lbuf);
togo -= thistime;
lptr = lbuf;
while(thistime--) {
zoomadd(lptr,rbuf,gbuf,bbuf,factor,xsize);
lptr += xsize;
y++;
if((y%factor) == 0) {
divrow(rbuf,rbuf,factor*factor,ixsize);
divrow(gbuf,gbuf,factor*factor,ixsize);
divrow(bbuf,bbuf,factor*factor,ixsize);
putrow(oimage,rbuf,(y-1)/factor,0);
putrow(oimage,gbuf,(y-1)/factor,1);
putrow(oimage,bbuf,(y-1)/factor,2);
zerorow(rbuf,ixsize);
zerorow(gbuf,ixsize);
zerorow(bbuf,ixsize);
}
}
}
iclose(oimage);
if(glgetmode()&DOUBLEBUFFER)
readsource(SRC_BACK);
free(lbuf);
free(rbuf);
free(gbuf);
free(bbuf);
}
static zoomadd(cptr,rbuf,gbuf,bbuf,factor,n)
unsigned char *cptr;
short *rbuf, *gbuf, *bbuf;
int factor, n;
{
int f;
f = factor;
while(n--) {
cptr++;
*bbuf += cptr[0];
*gbuf += cptr[1];
*rbuf += cptr[2];
cptr += 3;
if(--f == 0) {
f = factor;
rbuf++;
gbuf++;
bbuf++;
}
}
}
/*
* lbuftoimage -
* do a filtered zoom on an array of longs into
* an image file.
*
*/
static int gz;
static IMAGE *gimage;
static unsigned long *glbuf;
static int gbxsize, gbysize;
static ggetimgrow(buf,y)
short *buf;
int y;
{
unsigned long *lptr;
int n, shift;
lptr = glbuf+(y*gbxsize);
shift = 8*gz;
n = gbxsize;
while(n--)
*buf++ = ((*lptr++)>>shift)&0xff;
}
static gputimgrow(buf,y)
short *buf;
int y;
{
putrow(gimage,buf,y,gz);
}
lbuftoimage(lbuf,bxsize,bysize,name,ixsize,iysize,filter)
unsigned long *lbuf;
int bxsize, bysize;
char *name;
int ixsize, iysize, filter;
{
gimage = iopen(name,"w",RLE(1),3,ixsize,iysize,3);
glbuf = lbuf;
gbxsize = bxsize;
gbysize = bysize;
for(gz=0; gz<3; gz++)
filterzoom(ggetimgrow,gputimgrow,bxsize,bysize,ixsize,iysize,filter,1.0);
iclose(gimage);
}